/*
 *
 */
package com.ePadink;

public class Base64Format
{
  private static final char[] vals = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/', '=' };

  public byte[] decode64(String str)
  {
    byte[] bt = str.getBytes();
    changeBytes(bt);
    int arrsize = bt.length * 3 / 4;

    byte[] myArr = new byte[arrsize];
    int curr = 0;
    int pos = 0;
    byte[] mybt = new byte[4];
    boolean lastbytes = false;
    for (lastbytes = false; !lastbytes; pos += 3) {
      if (curr == bt.length - 4)
        lastbytes = true;
      dec4chars(bt, myArr, curr, pos, lastbytes);

      curr += 4;
    }

    int slack = 0;
    if (bt[(bt.length - 1)] == 64)
      slack = bt[(bt.length - 2)] == 64 ? 2 : 1;
    byte[] final_array = new byte[myArr.length - slack];
    System.arraycopy(myArr, 0, final_array, 0, myArr.length - slack);
    return final_array;
  }

  private static void changeBytes(byte[] arr) {
    for (int i = 0; i < arr.length; i++)
      if ((arr[i] >= 65) && (arr[i] <= 90))
      {
        int tmp26_25 = i; arr[tmp26_25] = ((byte)(arr[tmp26_25] - 65));
      } else if ((arr[i] >= 97) && (arr[i] <= 122))
      {
        int tmp54_53 = i; arr[tmp54_53] = ((byte)(arr[tmp54_53] - 71));
      } else if ((arr[i] >= 48) && (arr[i] <= 57))
      {
        int tmp82_81 = i; arr[tmp82_81] = ((byte)(arr[tmp82_81] + 4));
      } else if (arr[i] == 43)
      {
        int tmp101_100 = i; arr[tmp101_100] = ((byte)(arr[tmp101_100] + 19));
      } else if (arr[i] == 47)
      {
        int tmp121_120 = i; arr[tmp121_120] = ((byte)(arr[tmp121_120] + 16));
      } else if (arr[i] == 61)
      {
        int tmp141_140 = i; arr[tmp141_140] = ((byte)(arr[tmp141_140] + 3));
      }
  }

  private static void dec4chars(byte[] bt, byte[] myArr, int curr, int pos, boolean lastbytes) {
    byte[] frmbytes = new byte[4];
    byte[] tobytes = new byte[3];
    int ctr = 0;
    System.arraycopy(bt, curr, frmbytes, 0, 4);
    if (lastbytes)
      for (int i = 0; i < frmbytes.length; i++)
        if (frmbytes[i] == 64)
          ctr++;
    tobytes[0] = ((byte)((frmbytes[0] & 0x3F) * 4 + (frmbytes[1] & 0x30) / 16));
    tobytes[1] = ((byte)((frmbytes[1] & 0xF) * 16 + (frmbytes[2] & 0x3C) / 4));
    tobytes[2] = ((byte)((frmbytes[2] & 0x3) * 64 + (frmbytes[3] & 0x3F)));
    System.arraycopy(tobytes, 0, myArr, pos, 3 - ctr);
  }

  public String encode64(byte[] arr) {
    StringBuffer wholeStr = new StringBuffer((arr.length + 2) / 3);
    for (int curr = 0; curr < arr.length - 3; curr += 3)
      wholeStr.append(enc24bit(arr, curr));
    switch (arr.length % 3) {
    case 0:
      wholeStr.append(enc24bit(arr, arr.length - 3));
      break;
    case 1:
      wholeStr.append(enc8bit(arr));
      break;
    case 2:
      wholeStr.append(enc16bit(arr));
    }
    return wholeStr.toString();
  }

  private static String enc24bit(byte[] arr, int pos) {
    char[] myChar = new char[4];
    myChar[0] = vals[((arr[pos] & 0xFC) / 4)];
    myChar[1] = vals[((arr[pos] & 0x3) * 16 + (arr[(pos + 1)] & 0xF0) / 16)];
    int myInt = (arr[(pos + 1)] & 0xF) * 4 + (arr[(pos + 2)] & 0xC0) / 64;

    myChar[2] = vals[((arr[(pos + 1)] & 0xF) * 4 + (arr[(pos + 2)] & 0xC0) / 64)];
    myChar[3] = vals[(arr[(pos + 2)] & 0x3F)];
    return new String(myChar);
  }

  private static String enc16bit(byte[] arr) {
    char[] myChar = new char[4];
    int pos = arr.length - 2;
    myChar[0] = vals[((arr[pos] & 0xFC) / 4)];
    myChar[1] = vals[((arr[pos] & 0x3) * 16 + (arr[(pos + 1)] & 0xF0) / 16)];
    myChar[2] = vals[((arr[(pos + 1)] & 0xF) * 4)];
    myChar[3] = vals[64];
    return new String(myChar);
  }

  private static String enc8bit(byte[] arr) {
    char[] myChar = new char[4];
    int pos = arr.length - 1;
    myChar[0] = vals[((arr[pos] & 0xFC) / 4)];
    myChar[1] = vals[((arr[pos] & 0x3) * 16)];
    myChar[2] = vals[64];
    myChar[3] = vals[64];
    return new String(myChar);
  }
}